package com.hzzftech.watchdog.busi.service.impl;

import java.util.*;

import com.hzzftech.watchdog.busi.constants.BusiConstant;
import com.hzzftech.watchdog.busi.domain.KtDispatcher;
import com.hzzftech.watchdog.busi.domain.KtJob;
import com.hzzftech.watchdog.busi.mapper.KtDispatcherMapper;
import com.hzzftech.watchdog.busi.mapper.KtJobMapper;
import com.hzzftech.watchdog.busi.service.IKtJobService;
import com.hzzftech.watchdog.common.constant.ScheduleConstants;
import com.hzzftech.watchdog.quartz.util.ScheduleUtils;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hzzftech.watchdog.busi.mapper.KtDispatcherHangupMapper;
import com.hzzftech.watchdog.busi.domain.KtDispatcherHangup;
import com.hzzftech.watchdog.busi.service.IKtDispatcherHangupService;
import com.hzzftech.watchdog.common.core.text.Convert;
import org.springframework.transaction.annotation.Transactional;

/**
 * 任务挂起Service业务层处理
 * 
 * @author kt-watchdog
 * @date 2022-02-21
 */
@Service
public class KtDispatcherHangupServiceImpl implements IKtDispatcherHangupService 
{
    public static final Logger logger = LoggerFactory.getLogger(KtDispatcherHangupServiceImpl.class);

    @Autowired
    private KtDispatcherHangupMapper ktDispatcherHangupMapper;

    @Autowired
    private IKtJobService iKtJobService;

    private static Map<String, Timer> holdTimer = new HashMap<>();

    /**
     * 查询任务挂起
     * 
     * @param id 任务挂起主键
     * @return 任务挂起
     */
    @Override
    public KtDispatcherHangup selectKtDispatcherHangupById(Long id)
    {
        return ktDispatcherHangupMapper.selectKtDispatcherHangupById(id);
    }

    /**
     * 查询任务挂起列表
     * 
     * @param ktDispatcherHangup 任务挂起
     * @return 任务挂起
     */
    @Override
    public List<KtDispatcherHangup> selectKtDispatcherHangupList(KtDispatcherHangup ktDispatcherHangup)
    {
        return ktDispatcherHangupMapper.selectKtDispatcherHangupList(ktDispatcherHangup);
    }

    /**
     * 新增任务挂起
     * 
     * @param ktDispatcherHangup 任务挂起
     * @return 结果
     */
    @Override
    public int insertKtDispatcherHangup(KtDispatcherHangup ktDispatcherHangup)
    {
        return ktDispatcherHangupMapper.insertKtDispatcherHangup(ktDispatcherHangup);
    }

    /**
     * 修改任务挂起
     * 
     * @param ktDispatcherHangup 任务挂起
     * @return 结果
     */
    @Override
    public int updateKtDispatcherHangup(KtDispatcherHangup ktDispatcherHangup)
    {
        return ktDispatcherHangupMapper.updateKtDispatcherHangup(ktDispatcherHangup);
    }

    /**
     * 批量删除任务挂起
     * 
     * @param ids 需要删除的任务挂起主键
     * @return 结果
     */
    @Override
    public int deleteKtDispatcherHangupByIds(String ids)
    {
        String[] idsstr = Convert.toStrArray(ids);
        int count = 0;
        for (String id : idsstr) {
            Long _id = Long.parseLong(id);
            count += deleteKtDispatcherHangupById(_id);
        }
        return count;
    }

    /**
     * 删除任务挂起信息
     * 
     * @param id 任务挂起主键
     * @return 结果
     */
    @Override
    public int deleteKtDispatcherHangupById(Long id)
    {
        KtDispatcherHangup ktDispatcherHangup = ktDispatcherHangupMapper.selectKtDispatcherHangupById(id);
        String startKey = genkey(ktDispatcherHangup, 1);
        String endKey = genkey(ktDispatcherHangup, 2);
        Timer timerStart = holdTimer.get(startKey);
        Timer timerEnd = holdTimer.get(endKey);
        if (timerStart != null) {
            timerStart.cancel();
            holdTimer.remove(startKey);
        }
        if (timerEnd != null) {
            timerEnd.cancel();
            holdTimer.remove(endKey);
        }
        return ktDispatcherHangupMapper.deleteKtDispatcherHangupById(id);
    }

    @Autowired
    private Scheduler scheduler;

    @Override
    @Transactional
    public int hangUpJob(KtDispatcherHangup ktDispatcherHangup) {
        // 返回-1表示任务被禁用，无法挂起,返回0表示其他错误导致无法挂起任务
        KtJob job = iKtJobService.selectJobById(ktDispatcherHangup.getJobId());
        if (job.getStatus().equals(BusiConstant.STATUS_NO)) {
            return -1;
        }
        ktDispatcherHangup.setHangStatus(BusiConstant.NOT_HANG_UP);
        this.updateKtDispatcherHangup(ktDispatcherHangup);

        TimerTask hangUpTask = new TimerTask() {
            @Override
            public void run() {
                try {
                    iKtJobService.pauseJob(job);
                    ktDispatcherHangup.setHangStatus(BusiConstant.HANG_UP);
                    updateKtDispatcherHangup(ktDispatcherHangup);
                } catch (SchedulerException e) {
                    logger.error("挂起任务失败", e);
                    ktDispatcherHangup.setHangStatus(BusiConstant.HANG_UP_FAILED);
                    updateKtDispatcherHangup(ktDispatcherHangup);
                    holdTimer.remove(genkey(ktDispatcherHangup, 1));
                    holdTimer.remove(genkey(ktDispatcherHangup, 2));
                }
            }
        };
        Timer startTimer = new Timer();
        startTimer.schedule(hangUpTask, ktDispatcherHangup.getBeginTime());
        holdTimer.put(genkey(ktDispatcherHangup, 1), startTimer);

        TimerTask unHangUpTask = new TimerTask() {
            @Override
            public void run() {
                try {
                    Long jobId = job.getJobId();
                    String jobGroup = job.getJobGroup();
                    scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup));
                    job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
                    ScheduleUtils.createScheduleJob(scheduler, job);
                    iKtJobService.updateJob(job);
                    ktDispatcherHangup.setHangStatus(BusiConstant.HANG_UP_END);
                    updateKtDispatcherHangup(ktDispatcherHangup);
                    holdTimer.remove(genkey(ktDispatcherHangup, 1));
                    holdTimer.remove(genkey(ktDispatcherHangup, 2));
                } catch (Exception e) {
                    logger.error("挂起任务失败", e);
                    ktDispatcherHangup.setHangStatus(BusiConstant.HANG_UP_FAILED);
                    updateKtDispatcherHangup(ktDispatcherHangup);
                    holdTimer.remove(genkey(ktDispatcherHangup, 1));
                    holdTimer.remove(genkey(ktDispatcherHangup, 2));
                }
            }
        };

        Timer endTimer = new Timer();
        endTimer.schedule(unHangUpTask, ktDispatcherHangup.getEndTime());
        holdTimer.put(genkey(ktDispatcherHangup, 2), endTimer);

        return 1;
    }

    public String genkey(KtDispatcherHangup hangup, int type) {
        if (type == 1) {
            return hangup.getJobName() + "_"+hangup.getBeginTime().getTime()+"_"+hangup.getEndTime().getTime()+"_start";
        } else {
            return hangup.getJobName() + "_"+hangup.getBeginTime().getTime()+"_"+hangup.getEndTime().getTime()+"_end";
        }
    }
}
